package com.cloudweb.oa.expr;

import cn.js.fan.util.ErrMsgException;
import cn.js.fan.util.StrUtil;
import com.cloudweb.oa.api.ICalculateFunc;
import com.cloudweb.oa.api.IExprUtil;
import com.cloudweb.oa.api.ILicenseUtil;
import com.cloudweb.oa.utils.LicenseConstUtil;
import com.cloudweb.oa.utils.SpringUtil;
import com.cloudwebsoft.framework.util.LogUtil;
import com.redmoon.oa.base.IExprImpl;
import com.redmoon.oa.base.IFormDAO;
import com.redmoon.oa.base.IFuncImpl;
import com.redmoon.oa.flow.FormDb;
import com.redmoon.oa.flow.FormField;
import com.redmoon.oa.visual.func.FuncMgr;
import com.redmoon.oa.visual.func.FuncUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Component
public class ExprUtil implements IExprUtil {

    @Autowired
    ICalculateFunc calculateFunc;

    @Autowired
    ExprCache exprCache;

    @Autowired
    ILicenseUtil licenseUtil;

    final Pattern FUNC_NAME_PATTERN = Pattern.compile(
            "([A-Z0-9a-z-_]+)\\((.*?)\\)",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);

    /**
     * 找到原子算式，因为算式有可能是嵌套的
     */
    final Pattern FUNC_PATTERN = Pattern.compile(
            "([A-Z0-9a-z-_]+)\\(([^\\$]*?)\\)",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);

    final Pattern EVAL_PATTERN = Pattern.compile(
            "([A-Z0-9a-z-_]+)\\(([^\\$(]*?)\\)",
            Pattern.DOTALL | Pattern.CASE_INSENSITIVE);

    /**
     * 解析方法名
     * @param exprStr
     * @return
     */
    @Override
    public String[] parseExpr(String exprStr) {
        if (exprStr==null) { // || !exprStr.startsWith("$")) {
            return null;
        }

        Matcher m = FUNC_NAME_PATTERN.matcher(exprStr);
        // StringBuffer sb = new StringBuffer();
        if (m.find()) {
            String[] ary = new String[2];
            ary[0] = m.group(1); // 方法名
            ary[1] = m.group(2); // 参数
            return ary;
        }

        return null;
    }

    public String decodeHtml(String str) {
        str = str.replaceAll("&nbsp;", "\"");
        return str.replaceAll("&quot;", "\"");
    }

    /**
     * 调用方法呈现字段，如处理人事列表中的年龄字段（已弃用），改为在年龄默认值中用$Age(csrq)实现展现，同时便于导出
     * @param ff
     * @param fdao
     * @return
     */
    @Override
    public String render(FormField ff, IFormDAO fdao) {
        if (!licenseUtil.isEnabled(LicenseConstUtil.EXPR)) {
            return (licenseUtil.getCompErrMsg(LicenseConstUtil.EXPR));
        }

        String exprStr = ff.getExpr();
        // 调用函数
        boolean isMatched = false;
        do {
            isMatched = false;
            // 找到原子算式，因为算式有可能是嵌套的
            Matcher m = FUNC_PATTERN.matcher(exprStr);
            StringBuffer sb = new StringBuffer();
            while (m.find()) {
                isMatched = true;

                String[] myfunc = new String[2];
                myfunc[0] = m.group(1); // 方法名
                myfunc[1] = m.group(2); // 参数
                if (!StrUtil.isEmpty(myfunc[1])) {
                    myfunc[1] = decodeHtml(myfunc[1]);
                }

                String val = "1";

                ExprUnit fu = exprCache.getExprUnit(myfunc[0]);
                if (fu!=null) {
                    IExprImpl ifil = fu.getIExprImpl();
                    try {
                        val = StrUtil.getNullStr(ifil.func(fdao, myfunc));
                    }
                    catch (ErrMsgException e) {
                        LogUtil.getLog(com.redmoon.oa.visual.FuncUtil.class).error(e);
                        return m.group() + " " + e.getMessage();
                    }
                }
                else {
                    LogUtil.getLog(com.redmoon.oa.visual.FuncUtil.class).error(myfunc[0] + "不存在！");
                    return myfunc[0] + "不存在！";
                }

                m.appendReplacement(sb, val);
            }
            m.appendTail(sb);

            exprStr = sb.toString();
        }
        while (isMatched);

        // 判断是否为数字，如果不是，则再做一次四则运算
        if (!"".equals(exprStr) && !StrUtil.isDouble(exprStr)) {
            if (ff.getFieldType()==FormField.FIELD_TYPE_DOUBLE
                    || ff.getFieldType()==FormField.FIELD_TYPE_INT
                    || ff.getFieldType()==FormField.FIELD_TYPE_FLOAT
                    || ff.getFieldType()==FormField.FIELD_TYPE_LONG
                    || ff.getFieldType()==FormField.FIELD_TYPE_PRICE
            ) {
                try {
                    exprStr = StrUtil.getNullStr(calculateFunc.calculate(fdao, exprStr, 2, true));
                }
                catch (ErrMsgException e) {
                    return e.getMessage();
                }
            }
        }

        return exprStr;
    }

    /**
     * 取得算式的参数中关联的表单域，以逗号分隔
     * @Description:
     * @param ff
     * @return
     */
    @Override
    public String getFieldsRelatedOnChange(FormDb fd, FormField ff) {
        String exprStr = ff.getExpr();

        List<String> aryAll = new ArrayList<>();
        boolean isMatched = false;

        do {
            isMatched = false;
            StringBuffer sb = new StringBuffer();

            Matcher m = FUNC_PATTERN.matcher(exprStr);
            while (m.find()) {
                isMatched = true;

                String[] myfunc = new String[2];
                myfunc[0] = m.group(1); // 方法名
                myfunc[1] = m.group(2); // 参数
                if (!StrUtil.isEmpty(myfunc[1])) {
                    myfunc[1] = decodeHtml(myfunc[1]);
                }

                ExprUnit fu = exprCache.getExprUnit(myfunc[0]);
                if (fu != null) {
                    IExprImpl ifil = fu.getIExprImpl();
                    ArrayList<String> ary = ifil.getFieldsRelated(myfunc, fd);
                    if (ary!=null && ary.size() > 0) {
                        aryAll.addAll(ary);
                    }
                } else {
                    LogUtil.getLog(com.redmoon.oa.visual.FuncUtil.class).error(myfunc[0] + "不存在！");
                    return "";
                }
                String val = "1";
                m.appendReplacement(sb, val);
            }
            m.appendTail(sb);

            exprStr = sb.toString();
        } while (isMatched);

        // 如果没有匹配的，则说明是四则运算表达式
        if (!isMatched) {
            ArrayList<String> aryList = calculateFunc.getSymbolsWithBracket(exprStr);
            Object[] ary = aryList.toArray();
            for (Object o : ary) {
                String el = (String) o;
                if (!calculateFunc.isOperator(el)) {
                    // ary[i]可能为0.2这样的系数
                    if (!StrUtil.isDouble(el)) {
                        FormField ffSub = fd.getFormField(el);
                        if (ffSub != null) {
                            aryAll.add(ffSub.getName());
                        }
                    }
                }
            }
        }

        // 去重，删除重复项
        aryAll = aryAll.stream().distinct().collect(Collectors.toList());

        StringBuffer sb = new StringBuffer();
        for (String fieldName : aryAll) {
            StrUtil.concat(sb, ",", fieldName);
        }

        return sb.toString();
    }

    /**
     * 调用方法进行更新操作
     * @param funcStr
     * @param fdao
     * @return
     */
    @Override
    public String eval(String funcStr, IFormDAO fdao) {
        String[] ary = funcStr.split(";");
        for (String s : ary) {
            funcStr = s;

            // 调用函数
            boolean isMatched = false;
            FuncMgr fm = new FuncMgr();
            do {
                isMatched = false;
                // 找到原子算式，因为算式有可能是嵌套的
                Matcher m = EVAL_PATTERN.matcher(funcStr);
                StringBuffer sb = new StringBuffer();
                while (m.find()) {
                    isMatched = true;

                    String[] myfunc = new String[2];
                    myfunc[0] = m.group(1); // 方法名
                    myfunc[1] = m.group(2); // 参数

                    String val = "1";

                    ExprUnit fu = exprCache.getExprUnit(myfunc[0]);
                    if (fu!=null) {
                        IExprImpl exprImpl = fu.getIExprImpl();
                        val = StrUtil.getNullStr(exprImpl.func(fdao, myfunc));
                    }
                    else {
                        LogUtil.getLog(com.redmoon.oa.visual.FuncUtil.class).error(myfunc[0] + "不存在！");
                        return myfunc[0] + "不存在！";
                    }

                    m.appendReplacement(sb, val);
                }
                m.appendTail(sb);

                funcStr = sb.toString();
            }
            while (isMatched);
        }
        return funcStr;
    }

    public static void main(String[] args) {
        // 找到原子算式，因为算式有可能是嵌套的
        final Pattern EVAL_PATTERN = Pattern.compile(
                "([A-Z0-9a-z-_]+)\\(([^\\$(]*?)\\)",
                Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
        String s = "IF(记录状态==1, \"同意\", IF(记录状态==-4, \"拒绝\", \"\"))";
        Matcher m = EVAL_PATTERN.matcher(s);
        while (m.find()) {
            String[] myfunc = new String[2];
            myfunc[0] = m.group(1); // 方法名
            myfunc[1] = m.group(2); // 参数
            System.out.println("myfunc[0]=" + myfunc[0]);
            System.out.println("myfunc[1]=" + myfunc[1]);
        }
    }
}
